/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "resize_load.h"

#include <locale.h>
#include <stdbool.h>
#include <time.h>

#include "node.h"
#include "device_manager.h"
#include "hmfs_common.h"
#include "resize_load_sb.h"
#include "resize_load_cp.h"
#include "resize_load_sit.h"
#include "resize_load_nat.h"

namespace OHOS {
namespace Hmfs {
ResizeLoad::ResizeLoad(std::shared_ptr<HmfsConfigData> configPtr, std::shared_ptr<HmfsSbInfo> sbInfoPtr)
    : config_(configPtr), sbInfo_(sbInfoPtr)
{
}

void ResizeLoad::UpdateSuperBlock(struct SuperBlockData *superBlock, int sbMask)
{
    uint8_t *buf = static_cast<uint8_t *>(calloc(BLOCK_SZ, 1));
    ASSERT(buf);
    if (GetLeValue(superBlock->features) & HMFS_FEATURE_SB_CHKSUM) {
        uint32_t oldCrc = GetLeValue(superBlock->checksum);
        uint32_t newCrc = HmfsCommon::GetInstance().HmfsCalCrc32(HMFS_SUPER_MAGIC, superBlock, SB_CHKSUM_OFFSET);
        SetLeValue(superBlock->checksum, newCrc);
        HMFS_INFO("SuperBlock CRC is updated (0x%x -> 0x%x)", oldCrc, newCrc);
    }

    memcpy(buf + HMFS_SUPER_OFFSET, superBlock, sizeof(*superBlock));
    for (int32_t addr = SB0_ADDR; addr < SB_MAX_ADDR; addr++) {
        if (SB_MASK(addr) & sbMask) {
            int ret = HmfsIo::GetInstance().DevWriteBlock(buf, addr);
            ASSERT(ret >= 0);
        }
    }
    free(buf);
    HMFS_INFO("Done to update superblock");
}

int32_t ResizeLoad::InitSbInfo()
{
    HMFS_DEBUG("Enter InitSbInfo");
    struct SuperBlockData *superB = sbInfo_->rawSuper;
    sbInfo_->logSectorsPerBlk = GetLeValue(superB->logSectorsPerBlk);
    sbInfo_->logBlockSize = GetLeValue(superB->logBlockSize);;
    sbInfo_->blockSize = 1 << sbInfo_->logBlockSize;
    sbInfo_->logBlksPerSeg = GetLeValue(superB->logBlksPerSeg);
    sbInfo_->blocksPerSeg = 1 << sbInfo_->logBlksPerSeg;
    sbInfo_->segmentsPerSec = GetLeValue(superB->segsPerSection);
    sbInfo_->sectionsPerZone = GetLeValue(superB->sectionsPerZone);
    sbInfo_->totalSections = GetLeValue(superB->sectionCount);
    sbInfo_->totalNodeCount = (GetLeValue(superB->segmentCountInNAT) / 2) *
        sbInfo_->blocksPerSeg * NAT_ENTRY_PER_BLOCK;
    sbInfo_->rootInodeId = GetLeValue(superB->rootInodeId);
    sbInfo_->nodeInodeId = GetLeValue(superB->nodeInodeId);
    sbInfo_->metaInodeId = GetLeValue(superB->metaInodeId);
    sbInfo_->curVictimSec = NULL_SEGNO;

    for (int32_t i = 0; i < MAX_DEVICES; i++) {
        if (!superB->devices[i].path[0]) {
            HMFS_ERROR("superB->devices[i].path[0] = %s",(char *)superB->devices[i].path);
            break;
        }
        if (i != 0 ) {
            config_->devices[i].path = strdup((char *)superB->devices[i].path);
            // if (DeviceManager::GetInstance().GetDeviceInfo(i)) //TODO modify
            //     ASSERT(0);
        } else {
            ASSERT(!strcmp((char *)superB->devices[i].path, config_->devices[i].path.c_str()));
        }

        config_->devices[i].segmentCount = LE32_TO_NATIVE(superB->devices[i].segmentCount); // superB->devices[i].totalSegments换成了 segmentCount。TODO 确认是否正确
        if (i != 0) {
            config_->devices[i].startBlkId = config_->devices[i - 1].endBlkId + 1;
        }
        config_->devices[i].endBlkId = config_->devices[i].startBlkId + config_->devices[i].segmentCount *
            config_->blocksPerSegment - 1;
        if (i == 0) {
            config_->devices[i].endBlkId += GetLeValue(superB->segment0BlkId);
        }
        if (config_->zonedModel == HMFS_ZONED_NONE) {
            if (config_->devices[i].zonedModel == HMFS_ZONED_HM) {
                config_->zonedModel = HMFS_ZONED_HM;
            } else if (config_->devices[i].zonedModel == HMFS_ZONED_HA && config_->zonedModel != HMFS_ZONED_HM) {
                config_->zonedModel = HMFS_ZONED_HA;
            }
        }

        config_->nDevices = i + 1;
        HMFS_INFO("Device[%d] : %s blkaddr = %" PRIx64"--%" PRIx64"",
                i, config_->devices[i].path.c_str(), config_->devices[i].startBlkId, config_->devices[i].endBlkId);
    }
    if(DeviceManager::GetInstance().GetDeviceCount() == 1) {
        DeviceInfo *deviceInfo = DeviceManager::GetInstance().GetDeviceInfo(0);
        config_->devices[0].segmentCount = LE32_TO_NATIVE(superB->segmentCount);//TODO device.segmentCount?
        deviceInfo->segmentCount  = LE32_TO_NATIVE(superB->segmentCount);
        config_->devices[0].endBlkId = config_->devices[0].startBlkId + config_->devices[0].segmentCount * config_->blocksPerSegment - 1;
        config_->devices[0].endBlkId += GetLeValue(superB->segment0BlkId);
        deviceInfo->endBlkId = config_->devices[0].endBlkId;
        if (config_->zonedModel == HMFS_ZONED_NONE) {
            if (deviceInfo->zonedModel == HMFS_ZONED_HM) {
                config_->zonedModel = HMFS_ZONED_HM;
            } else if (deviceInfo->zonedModel == HMFS_ZONED_HA && config_->zonedModel != HMFS_ZONED_HM) {
                config_->zonedModel = HMFS_ZONED_HA;
            }
        }
    }
    uint64_t totalSectors = GetLeValue(superB->blockCount) << sbInfo_->logSectorsPerBlk;
    HMFS_INFO("Segments per section = %d", sbInfo_->segmentsPerSec);
    HMFS_INFO("Sections per zone = %d", sbInfo_->sectionsPerZone);
    HMFS_INFO("total FS sectors = %" PRIu64" (%" PRIu64" MB)",
        totalSectors, totalSectors >> (20 - GetLeValue(superB->logSectorSize)));
    return SUCCESS_CODE;
}

int32_t ResizeLoad::HmfsShouldProceed(struct SuperBlockData *sbData, uint32_t flag)
{
    HMFS_DEBUG("Enter HmfsShouldProceed");
    if (sbData == nullptr) {
        return EXIT_ERR_CODE;
    }
    if (!config_->fixOn && (config_->autoFix || config_->preenMode)) {
        if (flag & CP_FSCK_FLAG || flag & CP_QUOTA_NEED_FSCK_FLAG || config_->abnormalStop ||
            config_->hmfsErrors || (ExistQfIno(sbData) && (flag & CP_ERROR_FLAG))) {
            config_->fixOn = 1;
        } else if (!config_->preenMode) {
            //print_cp_state(flag);
            return EXIT_ERR_CODE;
        }
    }
    return SUCCESS_CODE;
}

int32_t ResizeLoad::UpdateSbFeatures()
{
    int sbIschanged = 0;
    struct SuperBlockData *sbData = sbInfo_->rawSuper;

    if (!(sbData->features & NATIVE_TO_LE32(HMFS_FEATURE_ENCRYPT)) &&
        config_->feature & NATIVE_TO_LE32(HMFS_FEATURE_ENCRYPT)) {
        sbData->features |= NATIVE_TO_LE32(HMFS_FEATURE_ENCRYPT);
        HMFS_INFO("Set Encryption feature");
        sbIschanged = 1;
    }
    if (!(sbData->features & NATIVE_TO_LE32(HMFS_FEATURE_CASEFOLD)) &&
        config_->feature & NATIVE_TO_LE32(HMFS_FEATURE_CASEFOLD)) {
        if (!config_->encoding) {
            HMFS_ERROR("ERROR: Must specify encoding to enable casefolding.");
            return EXIT_ERR_CODE;
        }
        sbData->features |= NATIVE_TO_LE32(HMFS_FEATURE_CASEFOLD);
        HMFS_INFO("Set Casefold feature");
        sbIschanged = 1;
    }
    /* TODO: quota needs to allocate inode numbers */

    config_->feature = sbData->features;
    if (!sbIschanged) {
        return SUCCESS_CODE;
    }
    UpdateSuperBlock(sbData, SB_MASK_ALL);
    return SUCCESS_CODE;
}

void *ResizeLoad::GetBitmapPtr(int flag)
{
    if (sbInfo_ == nullptr) {
        return nullptr;
    }
    CheckPointData *ckpt = sbInfo_->ckptData;
    SuperBlockData *sbData = sbInfo_->rawSuper;
    int32_t offset;

    if (IsSetCkptFlags(ckpt, CP_LARGE_NAT_BITMAP_FLAG)) {
        unsigned int chksumSize = 0;
        offset = (flag == SIT_BITMAP) ?
            LE32_TO_NATIVE(ckpt->natVersionBitmapSize) : 0;
        if (LE32_TO_NATIVE(ckpt->checksumOffset) ==
                    CP_MIN_CHKSUM_OFFSET)
            chksumSize = sizeof(uint32_t);

        return &ckpt->sitNatVersionBitmap[offset + chksumSize];
    }
    if (LE32_TO_NATIVE(sbData->cpPayload) > 0) {
        if (flag == NAT_BITMAP) {
            return &ckpt->sitNatVersionBitmap;
        } else {
            return ((char *)ckpt + HMFS_BLKSIZE);
        }
    } else {
        offset = (flag == NAT_BITMAP) ? LE32_TO_NATIVE(ckpt->sitVersionBitmapSize) : 0;
        return &ckpt->sitNatVersionBitmap[offset];
    }
}

uint32_t ResizeLoad::GetStartCpAddr()
{
    uint32_t startCpAddr = LE32_TO_NATIVE(sbInfo_->rawSuper->cpBlkId);
    if(sbInfo_->curCpId == 2) {
        startCpAddr += sbInfo_->blocksPerSeg;
    }
    return startCpAddr;
}

uint32_t ResizeLoad::GetNextFreeBlkAddr(struct CurSegmentInfo * curseg)
{
    uint32_t segNum = curseg->segNum;
    return sbInfo_->smInfoTable->mainBlkaddr + (segNum << sbInfo_->logBlksPerSeg)
     + curseg->nextBlkOffset;
}

bool ResizeLoad::HmfsIsValidBlkaddr(uint32_t blkaddr, int type)
{
    switch (type) {
        case META_NAT:
            break;
        case META_SIT: {
            if (blkaddr >= SIT_BLK_CNT(sbInfo_)) {
                return SUCCESS_CODE;
            }
            break;
        }
        case META_SSA: {
            if (blkaddr >= MAIN_BLKADDR(sbInfo_) || blkaddr < SM_I(sbInfo_)->ssaBlkaddr)  {
                return SUCCESS_CODE;
            }
            break;
        }
        case META_CP: {
            if (blkaddr >= SIT_I(sbInfo_)->sitBaseAddr || blkaddr < GetStartCpAddr()) {
                return SUCCESS_CODE;
            }
            break;
        }
        case META_POR: {
            if (blkaddr >= MAX_BLKADDR(sbInfo_) || blkaddr < MAIN_BLKADDR(sbInfo_)) {
                return SUCCESS_CODE;
            }
            break;
        }
        default:
            ASSERT(SUCCESS_CODE);
    }
    return EXIT_ERR_CODE;
}

struct FsyncInodeEntry* ResizeLoad::GetFsyncInode(struct ListNode *head, uint32_t ino)
{
    struct FsyncInodeEntry *entry;
    LIST_FOR_EACH_ENTRY(entry, head, FsyncInodeEntry, list) {
        if (entry->ino == ino) {
            return entry;
        }
    }
    return nullptr;
}

struct FsyncInodeEntry* ResizeLoad::AddFsyncinode(struct ListNode *head, uint32_t ino)
{
    struct FsyncInodeEntry *entry = static_cast<struct FsyncInodeEntry *>(calloc(sizeof(struct FsyncInodeEntry), 1));
    if (!entry) {
        return nullptr;
    }
    entry->ino = ino;
    ListTailInsert(head, &entry->list);
    return entry;
}

int32_t ResizeLoad::FindFsyncInode(struct ListNode *head)
{
    unsigned int loopCnt = 0;
    SegmentInfoTable * smInfo = sbInfo_->smInfoTable;
    unsigned int freeBlocks = smInfo->mainSegments * sbInfo_->blocksPerSeg -
                        sbInfo_->totalValidBlockCount;
    int err = 0;

    /* get node pages in the current segment */
    struct CurSegmentInfo *curseg = (struct CurSegmentInfo *) (smInfo->curSegmentArray + CURSEG_WARM_NODE);
    uint32_t blkaddr = GetNextFreeBlkAddr(curseg);

    struct NodeData *nodeBlk = static_cast<struct NodeData *>(calloc(HMFS_BLKSIZE, 1));
    ASSERT(nodeBlk);

    while (1) {
        struct FsyncInodeEntry *entry;

        if (!HmfsIsValidBlkaddr(blkaddr, META_POR)) {
            break;
        }
        err = HmfsIo::GetInstance().DevReadBlock(nodeBlk, blkaddr);
        if (err) {
            break;
        }
        if (!IsRecoverableDnode(sbInfo_, nodeBlk)) {
            break;
        }
        if (!IsFsyncDnode(nodeBlk)) {
            if (++loopCnt >= freeBlocks || blkaddr == NextBlkAddrOfNode(nodeBlk)) {
                HMFS_ERROR("\tdetect looped node chain, blkaddr");
                err = -1;
                break;
            }
            blkaddr = NextBlkAddrOfNode(nodeBlk);
            continue;
        }
        entry = GetFsyncInode(head, InoOfNode(nodeBlk));
        if (!entry) {
            entry = AddFsyncinode(head, InoOfNode(nodeBlk));
            if (!entry) {
                err = -1;
                break;
            }
        }
        entry->blkaddr = blkaddr;

        if (IsInode(nodeBlk) && IsDentDnode(nodeBlk))
            entry->last_dentry = blkaddr;

        /* sanity check in order to detect looped node chain */
        if (++loopCnt >= freeBlocks ||
            blkaddr == NextBlkAddrOfNode(nodeBlk)) {
            HMFS_ERROR("\tdetect looped node chain, blkaddr:%u, next:%u", blkaddr,
                NextBlkAddrOfNode(nodeBlk));
            err = -1;
            break;
        }
        blkaddr = NextBlkAddrOfNode(nodeBlk);
    }

    free(nodeBlk);
    return err;
}

/*
 * Readahead CP/NAT/SIT/SSA pages
 */
int32_t ResizeLoad::HmfsRaMetaPages(uint32_t start, int nrpages, int type)
{
    uint32_t blkno = start;
    uint32_t blkaddr;
    uint32_t startBlk = 0;
    uint32_t len = 0;
    for (; nrpages-- > 0; blkno++) {

        if (!HmfsIsValidBlkaddr(blkno, type)) {
            break;
        }

        switch (type) {
        case META_NAT:
            if (blkno >= NAT_BLOCK_OFFSET(NM_I(sbInfo_)->maxNid))
                blkno = 0;
            /* get nat block addr */
            blkaddr = CurrentNatAddr(sbInfo_, blkno * NAT_ENTRY_PER_BLOCK, nullptr);
            break;
        case META_SIT:
            /* get sit block addr */
            blkaddr = CurrentSitAddr(sbInfo_, blkno * SIT_ENTRIES_PER_BLOCK);
            break;
        case META_SSA:
        case META_CP:
        case META_POR:
            blkaddr = blkno;
            break;
        default:
            ASSERT(0);
        }

        if (!len) {
            startBlk = blkaddr;
            len = 1;
        } else if (startBlk + len == blkaddr) {
            len++;
        } else {
            HmfsIo::GetInstance().DevReadAhead(startBlk << HMFS_BLKSIZE_BITS);
        }
    }

    if (len) {
        HmfsIo::GetInstance().DevReadAhead(startBlk << HMFS_BLKSIZE_BITS);
    }
    return blkno - start;
}

int32_t ResizeLoad::DoRecordFsyncData(struct NodeData *node_blk, uint32_t blkaddr)
{
    unsigned int ofsInNode = 0;
    unsigned int start = 0;
    int err = 0; 
    int recorded = 0;
    unsigned int segno = GET_SEGNO(sbInfo_, blkaddr);
    struct SegEntry *se = GetSegEntry(sbInfo_, segno);
    unsigned int offset = OFFSET_IN_SEG(sbInfo_, blkaddr);
    if (HmfsCommon::GetInstance().HmfsTestBit(offset, (char *)se->curValidBitmap)) {
        ASSERT(0);
        return EXIT_ERR_CODE;
    }
    if (HmfsCommon::GetInstance().HmfsTestBit(offset, (char *)se->ckptValidBitmap)) {
        ASSERT(0);
        return EXIT_ERR_CODE;
    }

    if (!se->ckptValidBlocks) {
        se->ckptType = CURSEG_WARM_NODE;
    }
    se->ckptValidBlocks++;
    HmfsCommon::GetInstance().HmfsSetBit(offset, (char *)se->ckptValidBitmap);

    HMFS_INFO("do_record_fsync_data: [node] ino = %u, nid = %u, blkaddr = %u",
        InoOfNode(node_blk), OfsOfNode(node_blk), blkaddr);

    /* inline data */
    if (IsInode(node_blk) && (node_blk->i.iInline & HMFS_INLINE_DATA)) {
        return SUCCESS_CODE;
    }
    /* xattr node */
    if (OfsOfNode(node_blk) == XATTR_NODE_OFFSET) {
        return SUCCESS_CODE;
    }
    /* step 3: recover data indices */
    start = StartBidxOfNode(OfsOfNode(node_blk), node_blk);
    unsigned int end = start + ADDRS_PER_PAGE(sbInfo_, node_blk, nullptr);

    for (; start < end; start++, ofsInNode++) {
        blkaddr = DatablockAddr(node_blk, ofsInNode);

        if (!IsValidDataBlkAddr(blkaddr)) {
            continue;
        }
        if (!HmfsIsValidBlkaddr(blkaddr, META_POR)) {
            err = EXIT_ERR_CODE;
            HMFS_ERROR("It is invalid blkaddr!");
            return err;
        }

        segno = GET_SEGNO(sbInfo_, blkaddr);
        se = GetSegEntry(sbInfo_, segno);
        offset = OFFSET_IN_SEG(sbInfo_, blkaddr);
        if (HmfsCommon::GetInstance().HmfsTestBit(offset, (char *)se->curValidBitmap)) {
            continue;
        }
        if (HmfsCommon::GetInstance().HmfsTestBit(offset, (char *)se->ckptValidBitmap)) {
            continue;
        }
        if (!se->ckptValidBlocks) {
            se->ckptType = CURSEG_WARM_DATA;
        }
        se->ckptValidBlocks++;
        HmfsCommon::GetInstance().HmfsSetBit(offset, (char *)se->ckptValidBitmap);
        HMFS_INFO("do_record_fsync_data: [data] ino = %u, nid = %u, blkaddr = %u",
            InoOfNode(node_blk), OfsOfNode(node_blk), blkaddr);
        recorded++;
    }

    HMFS_INFO("recover_data: ino = %u, nid = %u, recorded = %d, err = %d",
        InoOfNode(node_blk), OfsOfNode(node_blk), recorded, err);
    return err;
}

void ResizeLoad::DelFsyncInode(struct FsyncInodeEntry *entry)
{
    ListDelete(&entry->list);
    free(entry);
}

int32_t ResizeLoad::TraverseDnodes(struct ListNode *inode_list)
{
    int32_t err = 0;
    /* get node pages in the current segment */
    struct CurSegmentInfo *curseg = CURSEG_I(sbInfo_, CURSEG_WARM_NODE);
    uint32_t blkaddr = NEXT_FREE_BLKADDR(sbInfo_, curseg);

    struct NodeData *node_blk = static_cast<struct NodeData *>(calloc(HMFS_BLKSIZE, 1));
    ASSERT(node_blk);

    while (1) {
        struct FsyncInodeEntry *entry;

        if (!HmfsIsValidBlkaddr(blkaddr, META_POR)) {
            break;
        }
        err = HmfsIo::GetInstance().DevReadBlock(node_blk, blkaddr);
        if (err) {
            break;
        }
        if (!IsRecoverableDnode(sbInfo_, node_blk)) {
            break;
        }
        entry = GetFsyncInode(inode_list, InoOfNode(node_blk));
        if (!entry) {
            blkaddr = NextBlkAddrOfNode(node_blk);
            continue;
        }
        err = DoRecordFsyncData(node_blk, blkaddr);
        if (err) {
            break;
        }
        if (entry->blkaddr == blkaddr){
            DelFsyncInode(entry);
        }

        blkaddr = NextBlkAddrOfNode(node_blk);
    }

    free(node_blk);
    return err;
}

void ResizeLoad::DestroyFsyncDnodes(struct ListNode *head)
{
    struct FsyncInodeEntry *entry;
    struct FsyncInodeEntry *tmp;
    LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, head, FsyncInodeEntry, list) {
        DelFsyncInode(entry);
    }
}

int32_t ResizeLoad::RecordFsyncData(ResizeLoadSit &loadSit)
{
    HMFS_DEBUG("Enter RecordFsyncData");
    struct ListNode iNodeList = { &iNodeList, &iNodeList };
    if (!NeedFsyncDataRecord(sbInfo_, config_)) {
        return SUCCESS_CODE;
    }
    uint32_t ret = FindFsyncInode(&iNodeList);
    if (ret) {
        HMFS_ERROR("Failed to find fsync inode");
        DestroyFsyncDnodes(&iNodeList);
        return ret;
    }

    ret = loadSit.LateBuildSegmentManager();
    if (ret != SUCCESS_CODE) {
        HMFS_ERROR("Failed to build segment manager");
        DestroyFsyncDnodes(&iNodeList);
        return ret;
    }

    ret = TraverseDnodes(&iNodeList);

    DestroyFsyncDnodes(&iNodeList);
    return ret;
}

int32_t ResizeLoad::HmfsLoadData()
{
    HMFS_DEBUG("Enter HmfsLoadData");
    if (sbInfo_ == nullptr) {
        return EXIT_ERR_CODE;
    }
    struct CheckPointData *cpData = nullptr;
    struct SuperBlockData *sbData = nullptr;
    sbInfo_->activeLogs = NR_CURSEG_TYPE;

	ResizeLoadSb loadSb(this);
	int32_t ret = loadSb.HmfsLoadSbData();
	if(ret != SUCCESS_CODE) {
		return EXIT_ERR_CODE;
	}
    sbData = sbInfo_->rawSuper;

    InitSbInfo();

    ResizeLoadCp loadCp(this);
	ret = loadCp.HmfsLoadCpData();
	if(ret != SUCCESS_CODE) {
		return EXIT_ERR_CODE;
	}

    cpData = sbInfo_->ckptData;
    if (config_->quotaFix) {
        if (GetLeValue(cpData->cpFlags) & CP_QUOTA_NEED_FSCK_FLAG)
            config_->fixOn = 1;
    }
    if (config_->layout) {
        return 1;
    }

    if (UpdateSbFeatures() != SUCCESS_CODE) {
        HMFS_ERROR("Failed to update superblock features");
        return EXIT_ERR_CODE;
    }

    /* precompute checksum seed for metadata */
    if (config_->feature & NATIVE_TO_LE32(HMFS_FEATURE_INODE_CHKSUM)) {
        config_->chksumSeed = HmfsCommon::GetInstance().HmfsCalCrc32(~0, sbData->uuid, sizeof(sbData->uuid));
    }
    sbInfo_->totalValidNodeCount = GetLeValue(cpData->validNodeCount);
    sbInfo_->totalValidInodeCount = GetLeValue(cpData->validInodeCount);
    sbInfo_->userBlockCount = GetLeValue(cpData->userBlockCount);
    sbInfo_->totalValidBlockCount = GetLeValue(cpData->validBlockCount);
    sbInfo_->lastValidBlockCount = sbInfo_->totalValidBlockCount;
    sbInfo_->allocValidBlockCount = 0;

	ResizeLoadSit loadSit(this);
    ResizeLoadNat loadNat(this);
    if (loadSit.BuildSegmentBegin() != SUCCESS_CODE) {
        HMFS_ERROR("Failed to build segment begin");
        return EXIT_ERR_CODE;
    }
    if (loadNat.BuildNodeManager() != SUCCESS_CODE) {
        HMFS_ERROR("Failed to build node manager");
        return EXIT_ERR_CODE;
    }
    if (RecordFsyncData(loadSit) != SUCCESS_CODE) {
        HMFS_ERROR("Failed to record fsync data");
        return EXIT_ERR_CODE;
    }
    if (HmfsShouldProceed(sbData, GetLeValue(cpData->cpFlags)) != SUCCESS_CODE) {
        HMFS_ERROR("Failed to proceed");
        return EXIT_ERR_CODE;
    }
    if (loadSit.LateBuildSegmentManager() != SUCCESS_CODE) {
        HMFS_ERROR("Failed to build segment manager");
        return EXIT_ERR_CODE;
    }
    if (loadNat.HmfsLateInitNidBitmap() != SUCCESS_CODE) {
        HMFS_ERROR("Failed to init nid bitmap");
        return EXIT_ERR_CODE;
    }
    return SUCCESS_CODE;
}

void ResizeLoad::HmfsUnLoadData()
{
    struct SitInfo *sitInfo = SIT_I(sbInfo_);
    struct SegmentInfoTable *smI = SM_I(sbInfo_);
    struct NodeAddressTable *nmI = NM_I(sbInfo_);
    /* free nm_info */
    // if (c.func == SLOAD || c.func == FSCK)
    //     free(nm_i->nid_bitmap);
    free(nmI->natBitmap);
    free(sbInfo_->naTable);
    /* free sit_info */
    free(sitInfo->bitmap);
    free(sitInfo->sitBitmap);
    free(sitInfo->segEntries);
    free(smI->sitInfo);
    /* free sm_info */
    for (uint32_t i = 0; i < NR_CURSEG_TYPE; i++) {
        free(smI->curSegmentArray[i].segSumBlk);
    }
    free(smI->curSegmentArray);
    free(sbInfo_->smInfoTable);
    free(sbInfo_->ckptData);
    free(sbInfo_->rawSuper);
}

std::shared_ptr<HmfsConfigData> ResizeLoad::GetConfig()
{
	return config_;
}

std::shared_ptr<HmfsSbInfo> ResizeLoad::GetSbInfo()
{
	return sbInfo_;
}

} // namespace Hmfs
} // namespace OHOS
